package cn.stylefeng.guns.cloud.workflow.modular.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.guns.cloud.libs.mp.page.PageFactory;
import cn.stylefeng.guns.cloud.model.page.PageResult;
import cn.stylefeng.guns.cloud.workflow.modular.model.params.RunOrEndProcessParam;
import cn.stylefeng.guns.cloud.workflow.modular.model.params.TaskParam;
import cn.stylefeng.guns.cloud.workflow.modular.model.result.RunProcessResult;
import cn.stylefeng.guns.cloud.workflow.modular.service.ActBaseService;
import cn.stylefeng.guns.cloud.workflow.modular.service.RunProcessService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.*;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 运行中流程 服务实现类
 *
 * @Author xuyuxiang
 * @Date 2019/11/14 17:25
 **/
@Service
public class RunProcessServiceImpl implements RunProcessService {

    private final String APPLY_USER_NAME = "applyUserName";

    private final String APPLY_DATE = "applyDate";

    private final String APPLY_USER_ID = "applyUserId";

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private ActBaseService actBaseService;


    /**
     * 运行中流程
     *
     * @Author xuyuxiang
     * @Date 2019/11/14 17:32
     **/
    @Override
    public PageResult list(RunOrEndProcessParam runProcessParam) {
        Page pageContext = this.getPageContext();

        List<HistoricTaskInstance> taskList = this.getRunTaskInstanceList(runProcessParam, pageContext);
        long count = this.countRunTaskInstance(runProcessParam);

        //将任务转换成RunProcessResult
        List<RunProcessResult> taskModelList = this.copyRunTaskListInfo(taskList);
        pageContext.setRecords(taskModelList);
        pageContext.setTotal(count);
        return new PageResult(pageContext);
    }

    /**
     * 获取运行中任务实例列表
     *
     * @Author xuyuxiang
     * @Date 2019/11/14 17:47
     **/
    private List<HistoricTaskInstance> getRunTaskInstanceList(RunOrEndProcessParam runProcessParam, Page pageContext) {

        HistoricProcessInstanceQuery historicProcessInstanceQuery = this.getRunTaskProcessInstanceQuery(runProcessParam);
        //获取历史流程实体列表
        List<HistoricProcessInstance> historicProcessInstanceList = historicProcessInstanceQuery.listPage((int) pageContext.getSize() * ((int) pageContext.getCurrent() - 1),
                (int) pageContext.getSize());
        //定义返回的任务历史流程实体列表
        List<HistoricTaskInstance> historicTaskInstanceList = new ArrayList<>();
        //获取最新任务节点信息
        for (HistoricProcessInstance historicProcessInstance : historicProcessInstanceList) {
            String processInstanceId = historicProcessInstance.getId();
            //获取historicTaskInstanceQuery
            HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService
                    .createHistoricTaskInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .orderByTaskCreateTime()
                    .desc();
            HistoricTaskInstance historicTaskInstance = historicTaskInstanceQuery.list().get(0);
            historicTaskInstanceList.add(historicTaskInstance);

        }
        return historicTaskInstanceList;
    }

    /**
     * 获取运行中流程HistoricProcessInstanceQuery
     *
     * @Author xuyuxiang
     * @Date 2019/11/14 18:19
     **/
    private HistoricProcessInstanceQuery getRunTaskProcessInstanceQuery(RunOrEndProcessParam runProcessParam) {
        HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery();

        String processName = runProcessParam.getProcessName();
        //根据流程名称查询
        if (ObjectUtil.isNotEmpty(processName)) {
            //根据流程名称查询流程定义实例集合
            ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionNameLike("%" + processName + "%");
            List<ProcessDefinition> processDefinitionList = processDefinitionQuery.list();
            //获取流程定义实例的key集合
            Set<String> processKeySet = new HashSet<>();
            for (ProcessDefinition processDefinition : processDefinitionList) {
                String key = processDefinition.getKey();
                processKeySet.add(key);
            }
            List<String> processKeyList = new ArrayList<>(processKeySet);
            historicProcessInstanceQuery.processDefinitionKeyIn(processKeyList);
        }
        //根据申请人查询
        String applyUserId = runProcessParam.getApplyUserId();

        if (ObjectUtil.isNotEmpty(applyUserId)) {
            historicProcessInstanceQuery.startedBy(applyUserId);
        }
        //流程未结束的
        historicProcessInstanceQuery.unfinished();

        return historicProcessInstanceQuery;
    }

    /**
     * 获取运行中任务实例数量
     *
     * @Author xuyuxiang
     * @Date 2019/11/14 17:47
     **/
    private long countRunTaskInstance(RunOrEndProcessParam runProcessParam) {
        return this.getRunTaskProcessInstanceQuery(runProcessParam).count();
    }

    /**
     * 将结果转换为RunProcessResult
     *
     * @Author xuyuxiang
     * @Date 2019/11/14 17:46
     **/
    private List<RunProcessResult> copyRunTaskListInfo(List<HistoricTaskInstance> taskList) {
        //返回的RunProcessResult集合
        List<RunProcessResult> runProcessResultList = new ArrayList<>();

        for (HistoricTaskInstance historicTaskInstance : taskList) {
            //任务id
            String taskId = historicTaskInstance.getId();

            //获取流程定义id
            String processDefinitionId = historicTaskInstance.getProcessDefinitionId();
            //获取流程定义实例
            ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId);
            //获取流程名称
            String processDefinitionName = processDefinition.getName();
            //流程实例id
            String processInstanceId = historicTaskInstance.getProcessInstanceId();

            //获取参数列表
            String applyUserId = "-";
            String applyUserName = "-";
            String applyDate = "-";
            List<HistoricVariableInstance> historicVariableInstanceList = historyService
                    .createHistoricVariableInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .list();
            for (HistoricVariableInstance historicVariableInstance : historicVariableInstanceList) {
                //获取参数名称
                String variableName = historicVariableInstance.getVariableName();
                //取出参数
                if (APPLY_USER_ID.equals(variableName)) {
                    //申请人id
                    applyUserId = historicVariableInstance.getValue().toString();
                }
                if (APPLY_USER_NAME.equals(variableName)) {
                    //申请人姓名
                    applyUserName = (String) historicVariableInstance.getValue();
                }
                if (APPLY_DATE.equals(variableName)) {
                    //申请人时间
                    applyDate = (String) historicVariableInstance.getValue();
                }

            }

            //任务名称
            String taskName = historicTaskInstance.getName();

            //待办人id
            String taskAssignee = historicTaskInstance.getAssignee();

            //待办人姓名
            String taskAssigneeUserName = "-";

            //待办人不存在，表示该任务为组任务,则不展示待办人姓名,只有待办人为具体人员时才展示
            if (ObjectUtil.isNotEmpty(taskAssignee)) {
                //待办人姓名
                taskAssigneeUserName = actBaseService.getNameByUserId(taskAssignee);
            }

            //委托人id
            String taskOwner = historicTaskInstance.getOwner();

            //委托人姓名
            String taskOwnerName = "-";


            //如果委托人不为空,则展示
            if (ObjectUtil.isNotEmpty(taskOwner)) {
                taskOwnerName = actBaseService.getNameByUserId(taskOwner);
            }

            //待办任务标题
            String taskTitle = processDefinitionName + "(" + applyUserName + " " + applyDate + ")";

            //获取任务
            Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();

            //是否挂起
            boolean suspended = task.isSuspended();

            //创建
            RunProcessResult runProcessResult = new RunProcessResult();
            runProcessResult.setTaskId(taskId);
            runProcessResult.setProcessDefinitionId(processDefinitionId);
            runProcessResult.setProcessInstanceId(processInstanceId);
            runProcessResult.setTaskTitle(taskTitle);
            runProcessResult.setProcessName(processDefinitionName);
            runProcessResult.setApplyUserId(applyUserId);
            runProcessResult.setApplyUserName(applyUserName);
            runProcessResult.setApplyDate(applyDate);
            runProcessResult.setApproveProcess(taskName);
            runProcessResult.setTaskAssigneeUserId(taskAssignee);
            runProcessResult.setTaskAssigneeUserName(taskAssigneeUserName);
            runProcessResult.setTaskOwnerUserId(taskOwner);
            runProcessResult.setTaskOwnerName(taskOwnerName);
            runProcessResult.setSuspended(suspended);
            runProcessResultList.add(runProcessResult);
        }
        return runProcessResultList;
    }

    /**
     * 挂起任务
     *
     * @Author xuyuxiang
     * @Date 2019/11/6 10:31
     **/
    @Override
    public void suspend(String processInstanceId) {
        runtimeService.suspendProcessInstanceById(processInstanceId);
    }

    /**
     * 激活任务
     *
     * @Author xuyuxiang
     * @Date 2019/11/6 10:32
     **/
    @Override
    public void active(String processInstanceId) {
        runtimeService.activateProcessInstanceById(processInstanceId);
    }


    /**
     * 转办（将此任务转为其他人审核）
     *
     * @Author xuyuxiang
     * @Date 2019/11/7 15:11
     **/
    @Override
    public void changeAssignee(TaskParam taskParam) {

        String processInstanceId = taskParam.getProcessInstanceId();

        String assigneeOrCandidateUserId = taskParam.getAssigneeOrCandidateUserId();

        Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
        //转办
        taskService.setAssignee(task.getId(), assigneeOrCandidateUserId);
    }

    /**
     * 结束
     *
     * @Author xuyuxiang
     * @Date 2019/11/20 16:17
     **/
    @Override
    public void end(String processInstanceId) {
        runtimeService.deleteProcessInstance(processInstanceId, "end");
    }

    /**
     * 获取pageContext
     *
     * @Author xuyuxiang
     * @Date 2019/10/25 16:04
     **/
    private Page getPageContext() {
        return PageFactory.defaultPage();
    }

}
